package cn.lichenfei.jfx.music.common;

import cn.hutool.core.lang.Console;
import cn.lichenfei.jfx.music.Application;
import cn.lichenfei.jfx.music.common.enums.PlayType;
import cn.lichenfei.jfx.music.common.model.AudioInfo;
import cn.lichenfei.jfx.music.common.model.MusicInfo;
import cn.lichenfei.jfx.music.common.model.TimeInfo;
import cn.lichenfei.jfx.music.common.utils.AudioDataUtil;
import javafx.application.Platform;
import javafx.collections.ObservableMap;
import javafx.scene.image.Image;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.util.Duration;

import java.io.File;
import java.util.List;
import java.util.Optional;
import java.util.Random;

/**
 * @author ChenFei
 * @date 2022/4/22
 */
public class MusicPlayer {

    public static List<AudioInfo> audioInfoList = AudioDataUtil.getAll();
    public static int currentIndex = 0;
    private static int volume = 20;
    private static MusicInfo currentMusicInfo;
    private static PlayType playType = PlayType.LIST_CYCLE;
    //
    private PlayerResult playerResult;
    private Media media;
    private MediaPlayer mediaPlayer;

    public MusicPlayer(PlayerResult playerResult) {
        new Thread(() -> Platform.runLater(() -> {
            //恢复之前的播放记录,音量
            Integer get = Config.getLastTimeMusic();
            volume = Config.getVolume().intValue();
            try{
                //设置当前音频数据
                this.currentIndex = get;
                setCurrentMusicInfo(audioInfoList.get(get));
            }catch (Exception e){
                //设置当前音频数据
                this.currentIndex = 0;
                setCurrentMusicInfo(audioInfoList.get(0));
            }
        })).start();
        this.playerResult = playerResult;
    }

    /**
     * 设置当前音乐
     *
     * @param audioInfo
     */
    private void setCurrentMusicInfo(AudioInfo audioInfo) {
        String path = audioInfo.getPath();
        if (audioInfo.getInternalResource()) {
            path = Application.class.getResource(path).getPath();
        }
        Console.log("index:{},音频文件路径：{}", currentIndex, path);
        path = new File(path).toURI().toString();
        media = new Media(path);
        mediaPlayer = new MediaPlayer(media);
        mediaPlayer.setAudioSpectrumInterval(0.1);
        setVolume(Double.valueOf(volume));//初始化音量大小
        //获取音乐信息
        currentMusicInfo = new MusicInfo();
        mediaPlayer.setOnReady(() -> {
            //获取音乐数据
            ObservableMap<String, Object> metadata = media.getMetadata();
            currentMusicInfo.setTitle((String) metadata.get("title"));
            currentMusicInfo.setAlbum((String) metadata.get("album"));
            currentMusicInfo.setArtist((String) metadata.get("artist"));
            currentMusicInfo.setImage((Image) metadata.get("image"));
            currentMusicInfo.setVolume(volume);
            Console.log("获取到音乐数据：{}", currentMusicInfo.toString());
            //返回音频媒体数据
            playerResult.resultMediaInfo(currentMusicInfo);
            //返回音频最大时长
            playerResult.resultTimeInfo(getTotalTime());
            //返回音频实时监听数据
            mediaPlayer.setAudioSpectrumListener((timestamp, duration, magnitudes, phases) -> {
                //推送监听数据
                playerResult.resultListener(timestamp, duration, magnitudes, phases, getCurrentTime());
            });
        });
        //音频播放结束事件
        mediaPlayer.setOnEndOfMedia(() -> {
            Console.log("播放完毕currentIndex：{}", currentIndex);
            switch (playType) {
                case LIST_CYCLE:
                    currentIndex++;
                    try {
                        audioInfoList.get(currentIndex);
                    } catch (IndexOutOfBoundsException e) {
                        currentIndex = 0;
                    }
                    break;
                case SHUFFLE:
                    currentIndex = new Random().nextInt(audioInfoList.size());
                    break;
                case ONE_CYCLE:
                    mediaPlayer.dispose();
                default:
                    break;
            }
            setCurrentMusicInfo(audioInfoList.get(currentIndex));
            playerResult.resultOnEnd();//播放完毕通知
            play();
        });

    }

    /**
     * 设置播放类似
     *
     * @param playType
     */
    public void setPlayType(PlayType playType) {
        Optional.ofNullable(playType).ifPresent(p -> {
            this.playType = p;
            Config.setPlayType(this.playType);
        });
    }

    public PlayType getPlayType() {
        return playType;
    }

    /**
     * 播放音乐
     *
     * @return
     */
    public void play() {
        Config.setLastTimeMusic(currentIndex);//记录当前播放的音乐
        mediaPlayer.play();
        playerResult.resultPlay();
    }

    public void play(int index) {
        currentIndex = index;
        mediaPlayer.dispose();//释放当前资源
        setCurrentMusicInfo(audioInfoList.get(index));
        play();
    }

    /**
     * 暂停音乐
     */
    public void pause() {
        mediaPlayer.pause();
        playerResult.resultPause();
    }

    /**
     * 设置音量
     *
     * @param volume
     */
    public void setVolume(double volume) {
        Config.setVolume(volume);
        mediaPlayer.setVolume(volume / 100);
        this.volume = (int) volume;
    }

    /**
     * 设置音乐播放时间
     *
     * @param seconds
     */
    public void setSeek(Double seconds) {
        mediaPlayer.seek(Duration.seconds(seconds));
    }


    /**
     * 获取当前音频时间
     *
     * @return
     */
    public TimeInfo getCurrentTime() {
        Double v = mediaPlayer.getCurrentTime().toSeconds();
        return new TimeInfo(v.intValue());
    }

    /**
     * 获取音频总时间
     *
     * @return
     */
    public TimeInfo getTotalTime() {
        Double v = mediaPlayer.getTotalDuration().toSeconds();
        return new TimeInfo(v.intValue());
    }

    /**
     * 下一首歌曲
     */
    public void nextMusic() {
        mediaPlayer.dispose();
        currentIndex++;
        if (currentIndex >= audioInfoList.size()) {
            currentIndex = 0;
        }
        setCurrentMusicInfo(audioInfoList.get(currentIndex));
        play();
    }

    /**
     * 上一首歌曲
     */
    public void previousMusic() {
        mediaPlayer.dispose();
        currentIndex--;
        if (currentIndex < 0) {
            currentIndex = audioInfoList.size() - 1;
        }
        setCurrentMusicInfo(audioInfoList.get(currentIndex));
        play();
    }
}
